using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Services;
using Microsoft.Xna.Framework.Graphics;
using Sudoku.Lang;
using Microsoft.Xna.Framework.GamerServices;
using Sudoku.Utilities;

namespace Sudoku.GamePlay
{
	public class EndGameScreen : ExtendedGameComponent
	{
		Boolean isWin;
		IInputManager inputService;
		IBoard board;
		IScoreService scoreService;

		Rectangle bgRect;
		Texture2D bg;
		Color bgColor;
		Texture2D bgImg;
		Rectangle bgImgRect;

		Texture2D bgTime;
		Texture2D bgHints;
		Texture2D bgTot;
		Texture2D bgX;
		Texture2D bgEqual;
		Texture2D bgPlus;

		Rectangle bgTimeRect;
		Rectangle bgHintsRect;
		Rectangle bgTotRect;
		Rectangle bgXRect;
		Rectangle bgEqualRect;
		Rectangle bgPlusRect;

		SpriteFont headerFont;
		Color headerColor;
		String header1;
		String header2;
		Vector2 headerLn1;
		Vector2 headerLn2;

		string diff;
		Color diffColor;
		Vector2 diffPos;

		SpriteFont scoreFont;
		Color scoreColor;
		Vector2 scoreLn0;
		Vector2 scoreLn1;
		Vector2 scoreLn2;
		Vector2 scoreLn3;
		Vector2 scoreLn4;
		string score0;
		string score1;
		string score2;
		string score3;
		string score4;

		SpriteFont messageFont;
		string message;
		Vector2 messagePos;

		SpriteFont font;

		Score score; 
		HighScore hScore;
		bool isNewRecord;
		int totTime;

		bool canReleaseScene = false;

		public EndGameScreen(Game game, Boolean win)
			: base (game)
		{
			isWin = win;
			this.DrawOrder = (int)ComponentOrders.UI;
		}

		public override void Initialize()
		{
			base.Initialize();

			soundService.PlaySound(SoundType.BoardComplete); 
			
			board = Game.Services.GetService(typeof(IBoard)) as IBoard;
			scoreService = Game.Services.GetService(typeof(IScoreService)) as IScoreService;
			
			score = board.GetScore();
			hScore = scoreService.RetrieveScore();
			int oldRecord = hScore.GetDifficultyRecord(score.Difficulty);
			totTime = ((int)score.Time + (score.Hints * 30));

			isNewRecord = (isWin && (oldRecord == 0 || oldRecord > totTime));

			//BACKGROUND
			bg = textureService.Texture("WhiteFill");
			bgColor = new Color(255, 255, 255, 230);
			bgRect = new Rectangle(0, 0, 480, 800);

			if (!isWin)
			{
				bgImg = textureService.Texture("Pellicano");
				bgImgRect = new Rectangle(123, 140, 234, 256);
			}
			else 
			{
				string name = (isNewRecord) ? "Gold" : "Blue";
				bgImg = textureService.Background(name + "Karp");
				bgHints = textureService.Texture(name + "Hint");
				bgTime = textureService.Texture(name + "Time");
				bgTot = textureService.Texture(name + "Tot");
				bgPlus = textureService.Texture("Plus");
				bgX = textureService.Texture("X");
				bgEqual = textureService.Texture("Equal");

				int add = (isNewRecord) ? 15 : 0 ;

				bgImgRect = new Rectangle(138, 105, 203, 256);
				bgTimeRect = new Rectangle(100, 555 + add, 52, 52);
				bgHintsRect = new Rectangle(100, 610 + add, 52, 52);
				bgTotRect = new Rectangle(100, 665 + add, 52, 52);
				bgPlusRect = new Rectangle(375, 570 + add, 24, 24);
				bgXRect = new Rectangle(303, 625 + add, 24, 24);
				bgEqualRect = new Rectangle(375, 625 + add, 24, 24);
			} 

			
			//HEADER
			headerFont = (isWin) ? fontService.Font(FontType.Delicious48) : fontService.Font(FontType.DeliciousSmallCaps28);
			if (isNewRecord || !isWin)
			{
				header1 = (isWin) ? LocalizedStrings.EndRecord1 : LocalizedStrings.EndLose1;
				header2 = (isWin) ? LocalizedStrings.EndRecord2 : LocalizedStrings.EndLose2;
				headerLn1 = new Vector2(240 - (headerFont.MeasureString(header1).X * 0.5f), (isWin) ? 370 : 420); 
				headerLn2 = new Vector2(240 - (headerFont.MeasureString(header2).X * 0.5f), (isWin) ? 430 : 460);
				headerColor = (isWin) ? new Color(204, 153, 0) : new Color(102, 0, 51);
			}
			else 
			{
				header1 =  LocalizedStrings.EndWin;
				headerColor = new Color(0, 102, 153) ;
				headerLn1 = new Vector2(240 - (headerFont.MeasureString(header1).X * 0.5f), 380);
			}

			//SCORE
			font = fontService.Font(FontType.Delicious36);

			diff = GetDifficultyString(score.Difficulty);
			diffColor = (isNewRecord) ? new Color(204, 102, 51)  : new Color(102, 0, 51);
			diffPos = new Vector2(240 - (font.MeasureString(diff).X * 0.5f), 35);


			scoreFont = fontService.Font(FontType.DeliciousSmallCaps28);
			scoreColor = (isNewRecord) ? new Color(204, 102, 51) : new Color(0, 89, 124);
			score0 = LocalizedStrings.EndScore;
			score1 = Utils.GetTimeString((int)score.Time); 
			score2 = Utils.GetTimeString(30);
			score3 = score.Hints.ToString();
			score4 = Utils.GetTimeString(totTime);
			
			scoreLn0 = (isNewRecord) ? new Vector2(240 - (font.MeasureString(score0).X * 0.5f), 510) : new Vector2(240 - (font.MeasureString(score0).X * 0.5f), 490);
			scoreLn1 = (isNewRecord) ? new Vector2(165, 575) : new Vector2(165, 560);
			scoreLn2 = (isNewRecord) ? new Vector2(165, 630) : new Vector2(165, 615);
			scoreLn3 = (isNewRecord) ? new Vector2(340, 630) : new Vector2(340, 615);
			scoreLn4 = (isNewRecord) ? new Vector2(165, 685) : new Vector2(165, 670);

			//MESSAGE
			messageFont = fontService.Font(FontType.DeliciousSmallCaps22);
			if (!isWin) message = LocalizedStrings.EndMessageLose;
			else message = (isNewRecord) ? LocalizedStrings.EndMessageRecord : LocalizedStrings.EndMessageWin;
			messagePos = new Vector2(240 - (messageFont.MeasureString(message).X * 0.5f), 750);

			canReleaseScene = false;

		}

		protected override void LoadContent()
		{
			base.LoadContent();

			inputService = Game.Services.GetService(typeof(IInputManager)) as IInputManager;
			inputService.OnTap += new InputManager.TouchEvent(OnTap);
		}

		private void OnTap(Vector2 touchPosition)
		{
			if (isWin)
			{
				if (isNewRecord)
				{
#if WINDOWS || XBOX
					soundService.PlaySound(SoundType.Fumble);
					StateManagement.StateManager.StartMenu(Game);
#else
					Guide.BeginShowKeyboardInput(
						PlayerIndex.One,
						LocalizedStrings.RecordTitle,
						LocalizedStrings.RecordText,
						"",
						new AsyncCallback(OnNameInput),
						null);
#endif
				}
				else
				{
					canReleaseScene = true; 
				}
			}
			else
			{
				canReleaseScene = true;
			}
		}

		private void OnNameInput(IAsyncResult result)
		{
			String name = Guide.EndShowKeyboardInput(result);

			soundService.PlaySound(SoundType.Fumble);
			
			// Save
			hScore.SetDifficultyRecord(score.Difficulty, totTime);
			hScore.SetDifficultyRecordName(score.Difficulty, name);
			canReleaseScene = true;
		}

		private string GetDifficultyString(Difficulty d)
		{
			string result="";

			switch (d)
			{ 
				case Difficulty.Beginner:
					result = LocalizedStrings.MenuBeginner;
					break;
				case Difficulty.Normal:
					result = LocalizedStrings.MenuNormal;
					break;
				case Difficulty.Experienced:
					result = LocalizedStrings.MenuExperienced;
					break;
				case Difficulty.Extreme:
					result = LocalizedStrings.MenuExtreme;
					break;
			}

			return result;
		}


		public override void Update(GameTime gameTime)
		{
			if (canReleaseScene)
			{
				inputService.OnTap -= new InputManager.TouchEvent(OnTap);
				Game.Components.Remove(this);
				
				soundService.PlaySound(SoundType.Fumble);
					
				if (isWin)
				{
					if (isNewRecord)
					{
						scoreService.SaveScore(hScore);
					}

					StateManagement.StateManager.StartMenu(Game);
				}
				else
				{
					foreach (GameComponent c in Game.Components)
						c.Enabled = true;
				}
			}
			base.Update(gameTime);
		}

		public override void Draw(GameTime gameTime)
		{
			spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied);
			spriteBatch.Draw(bg, bgRect, bgColor);
			spriteBatch.End();

			spriteBatch.Begin();

			spriteBatch.DrawString(headerFont, header1, headerLn1, headerColor);
			
			spriteBatch.Draw(bgImg, bgImgRect, Color.White);

			if (isWin)
			{

				if (isNewRecord) spriteBatch.DrawString(headerFont, header2, headerLn2, headerColor);

				spriteBatch.Draw(bgTime, bgTimeRect, Color.White);
				spriteBatch.Draw(bgHints, bgHintsRect, Color.White);
				spriteBatch.Draw(bgTot, bgTotRect, Color.White);
				spriteBatch.Draw(bgPlus, bgPlusRect, headerColor);
				spriteBatch.Draw(bgX, bgXRect, headerColor);
				spriteBatch.Draw(bgEqual, bgEqualRect, headerColor);

				spriteBatch.DrawString(font, diff, diffPos, diffColor);

				spriteBatch.DrawString(font, score0, scoreLn0, diffColor);
				spriteBatch.DrawString(scoreFont, score1, scoreLn1, scoreColor);
				spriteBatch.DrawString(scoreFont, score2, scoreLn2, scoreColor);
				spriteBatch.DrawString(scoreFont, score3, scoreLn3, scoreColor);
				spriteBatch.DrawString(scoreFont, score4, scoreLn4, scoreColor);
			}
			else spriteBatch.DrawString(headerFont, header2, headerLn2, headerColor);

			spriteBatch.DrawString(messageFont, message, messagePos, headerColor);

			spriteBatch.End();

			base.Draw(gameTime);
		}
	}
}
